#!/usr/bin/guile \
-e main -s
!#

;; syntax-rules  literals (pattern template)
;; there are an equal number of patterns and templates
;; the first matching pattern is used

;;patters can be made of:
;;lists, improper lists, vectors, identifiers, and datums.

(define-syntax when
  (syntax-rules ()
    ((when condition exp ...)
     (if condition
         (begin exp ...)))))

;; this macro will match (let1 (foo 'bar))
(define-syntax let1
  (syntax-rules ()
    ((_ (var val) exp ...)
     (let ((var val)) exp ...))))

;; this will not match (let1 (foo 'bar))
(define-syntax let1
  (syntax-rules ()
    ((_ (var val) exp exp* ...)
     (let ((var val)) exp* ...))))

;; making a print macro to print out a newline at the end of the
;; display statement

;; works
(define-syntax print
  (syntax-rules ()
    ((print exp)
     (display (string-append exp "\n")))))

;; works
(define-syntax print
  (syntax-rules ()
    ((_ exp)
     (display (string-append exp "\n")))))

;; works
(define-syntax print
  (syntax-rules ()
    ((_ exp)
     (display (string-append exp "\n")))
    ((print exp exp2)
     (display (string-append exp exp2 "\n")))))

;; works
(define-syntax print
  (syntax-rules ()
    ((_ exp)
     (display (string-append exp "\n")))
    ((print exp exp2)
     (display (string-append exp exp2 "\n")))
    ((print exp exp2 ...)
     (display (string-append exp exp2 ... "\n")))))

(define-syntax print
  (syntax-rules ()
    ((_ exp)
     (display (string-append exp "\n")))
    ((print exp ...)
     (display (string-append exp ... "\n")))))

;; a macro that calls two different functions, depending on the number
;; of arguments.
(define-syntax distance
  (syntax-rules ()
    ((distance x y)
     (distance-x-y x y))
    ((distance x y z)
     (distance-x-y-z x y z))))

;; doesn't work
(define-syntax playing
  (syntax-rules (cool bear frozen)
    ((playing (cool exp (bear exp2 (frozen exp3))))
     (+ 5 2))))

;;works
(define-syntax playing
  (syntax-rules (cool )
    ((playing (cool))
     (+ 5 2))))

;; works
(define-syntax playing
  (syntax-rules (cool bear)
    ((playing (cool (bear (anything))))
     (+ 5 2))))

;; works
(define-syntax playing
  (syntax-rules (cool bear)
    ((playing exp (cool (bear)))
     (+ 5 2 exp))))


(define-syntax my-define-record-type
  (syntax-rules ()
    ((my-define-record-type type
                            constructor
                            constructor?
                            (fieldname var1) ...)
     (define-record-type type
       (constructor fieldname  ...)
       constructor?
       (fieldname var1) ... ))))
